home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / src / icon.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-20  |  25.0 KB  |  972 lines

  1. /* icon.c - window icon and dock and appicon parent
  2.  * 
  3.  *  Window Maker window manager
  4.  * 
  5.  *  Copyright (c) 1997, 1998 Alfredo K. Kojima
  6.  * 
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
  20.  *  USA.
  21.  */
  22.  
  23. #include "wconfig.h"
  24.  
  25. #include <X11/Xlib.h>
  26. #include <X11/Xutil.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <unistd.h>
  31. #include <ctype.h>
  32. #include <wraster.h>
  33. #include <sys/stat.h>
  34.  
  35. #include "WindowMaker.h"
  36. #include "wcore.h"
  37. #include "texture.h"
  38. #include "window.h"
  39. #include "icon.h"
  40. #include "actions.h"
  41. #include "funcs.h"
  42. #include "stacking.h"
  43. #include "application.h"
  44. #include "defaults.h"
  45. #include "appicon.h"
  46.  
  47. /**** Global variables ****/
  48. extern WPreferences wPreferences;
  49.  
  50. #define MOD_MASK wPreferences.modifier_mask
  51.  
  52. extern Cursor wCursor[WCUR_LAST];
  53.  
  54.  
  55. static void miniwindowExpose(WObjDescriptor *desc, XEvent *event);
  56. static void miniwindowMouseDown(WObjDescriptor *desc, XEvent *event);
  57. static void miniwindowDblClick(WObjDescriptor *desc, XEvent *event);
  58.  
  59.  
  60. /****** Notification Observers ******/
  61.  
  62. static void
  63. appearanceObserver(void *self, WMNotification *notif)
  64. {
  65.     WIcon *icon = (WIcon*)self;
  66.     int flags = (int)WMGetNotificationClientData(notif);
  67.  
  68.     if (flags & WTextureSettings) {
  69.     icon->force_paint = 1;
  70.     }
  71.     if (flags & WFontSettings) {
  72.     icon->force_paint = 1;
  73.     }
  74.     /*
  75.     if (flags & WColorSettings) {
  76.     }
  77.      */
  78.  
  79.     wIconPaint(icon);
  80.  
  81.     /* so that the appicon expose handlers will paint the appicon specific 
  82.      * stuff */
  83.     XClearArea(dpy, icon->core->window, 0, 0, icon->core->width, 
  84.            icon->core->height, True);
  85. }
  86.  
  87.  
  88. static void
  89. tileObserver(void *self, WMNotification *notif)
  90. {
  91.     WIcon *icon = (WIcon*)self;
  92.  
  93.     icon->force_paint = 1;
  94.     wIconPaint(icon);
  95.  
  96.     XClearArea(dpy, icon->core->window, 0, 0, 1, 1, True);
  97. }
  98.  
  99. /************************************/
  100.  
  101.  
  102.  
  103. INLINE static void
  104. getSize(Drawable d, unsigned int *w, unsigned int *h, unsigned int *dep)
  105. {
  106.     Window rjunk;
  107.     int xjunk, yjunk;
  108.     unsigned int bjunk;
  109.     
  110.     XGetGeometry(dpy, d, &rjunk, &xjunk, &yjunk, w, h, &bjunk, dep);
  111. }
  112.  
  113.  
  114. WIcon*
  115. wIconCreate(WWindow *wwin)
  116. {
  117.     WScreen *scr=wwin->screen_ptr;
  118.     WIcon *icon;
  119.     char *file;
  120.     unsigned long vmask = 0;
  121.     XSetWindowAttributes attribs;
  122.     
  123.     icon = wmalloc(sizeof(WIcon));
  124.     memset(icon, 0, sizeof(WIcon));
  125.     icon->core = wCoreCreateTopLevel(scr, wwin->icon_x, wwin->icon_y,
  126.                      wPreferences.icon_size, 
  127.                      wPreferences.icon_size, 0);
  128.     
  129.     if (wPreferences.use_saveunders) {
  130.     vmask |= CWSaveUnder;
  131.     attribs.save_under = True;
  132.     }
  133.     /* a white border for selecting it */
  134.     vmask |= CWBorderPixel;
  135.     attribs.border_pixel = scr->white_pixel;
  136.     
  137.     XChangeWindowAttributes(dpy, icon->core->window, vmask, &attribs);
  138.  
  139.     
  140.     /* will be overriden if this is an application icon */
  141.     icon->core->descriptor.handle_mousedown = miniwindowMouseDown;
  142.     icon->core->descriptor.handle_expose = miniwindowExpose;
  143.     icon->core->descriptor.parent_type = WCLASS_MINIWINDOW;
  144.     icon->core->descriptor.parent = icon;
  145.     
  146.     icon->core->stacking = wmalloc(sizeof(WStacking));
  147.     icon->core->stacking->above = NULL;
  148.     icon->core->stacking->under = NULL;
  149.     icon->core->stacking->window_level = NORMAL_ICON_LEVEL;
  150.     icon->core->stacking->child_of = NULL;
  151.  
  152.     icon->owner = wwin;
  153.     if (wwin->wm_hints && (wwin->wm_hints->flags & IconWindowHint)) {
  154.     if (wwin->client_win == wwin->main_window) {
  155.         WApplication *wapp;
  156.         /* do not let miniwindow steal app-icon's icon window */
  157.         wapp = wApplicationOf(wwin->client_win);
  158.         if (!wapp || wapp->app_icon==NULL)
  159.         icon->icon_win = wwin->wm_hints->icon_window;
  160.     } else {
  161.         icon->icon_win = wwin->wm_hints->icon_window;
  162.     }
  163.     }
  164. #ifdef NO_MINIWINDOW_TITLES
  165.     icon->show_title = 0;
  166. #else
  167.     icon->show_title = 1;
  168. #endif
  169.     icon->image = wDefaultGetImage(scr, wwin->wm_instance, wwin->wm_class);
  170.  
  171.     file = wDefaultGetIconFile(scr, wwin->wm_instance, wwin->wm_class,
  172.                    False);
  173.     if (file) {
  174.         icon->file = wstrdup(file);
  175.     }
  176.  
  177.     wGetIconName(dpy, wwin->client_win, &icon->icon_name);
  178.  
  179.     icon->tile_type = TILE_NORMAL;
  180.     
  181.     wIconUpdate(icon);
  182.     
  183.     XFlush(dpy);
  184.  
  185.     WMAddNotificationObserver(appearanceObserver, icon, 
  186.                   WNIconAppearanceSettingsChanged, icon);
  187.     WMAddNotificationObserver(tileObserver, icon, 
  188.                   WNIconTileSettingsChanged, icon);
  189.     return icon;
  190. }
  191.  
  192.  
  193. WIcon*
  194. wIconCreateWithIconFile(WScreen *scr, char *iconfile, int tile)
  195. {
  196.     WIcon *icon;
  197.     unsigned long vmask = 0;
  198.     XSetWindowAttributes attribs;
  199.  
  200.     icon = wmalloc(sizeof(WIcon));
  201.     memset(icon, 0, sizeof(WIcon));
  202.     icon->core = wCoreCreateTopLevel(scr, 0, 0, wPreferences.icon_size, 
  203.                      wPreferences.icon_size, 0);
  204.     if (wPreferences.use_saveunders) {
  205.     vmask = CWSaveUnder;
  206.     attribs.save_under = True;
  207.     }
  208.     /* a white border for selecting it */
  209.     vmask |= CWBorderPixel;
  210.     attribs.border_pixel = scr->white_pixel;
  211.     
  212.     XChangeWindowAttributes(dpy, icon->core->window, vmask, &attribs);
  213.  
  214.     /* will be overriden if this is a application icon */
  215.     icon->core->descriptor.handle_mousedown = miniwindowMouseDown;
  216.     icon->core->descriptor.handle_expose = miniwindowExpose;
  217.     icon->core->descriptor.parent_type = WCLASS_MINIWINDOW;
  218.     icon->core->descriptor.parent = icon;
  219.  
  220.     icon->core->stacking = wmalloc(sizeof(WStacking));
  221.     icon->core->stacking->above = NULL;
  222.     icon->core->stacking->under = NULL;
  223.     icon->core->stacking->window_level = NORMAL_ICON_LEVEL;
  224.     icon->core->stacking->child_of = NULL;
  225.  
  226.     if (iconfile) {
  227.     icon->image = RLoadImage(scr->rcontext, iconfile, 0);
  228.     if (!icon->image) {
  229.         wwarning(_("error loading image file \"%s\""), iconfile, RMessageForError(RErrorCode));
  230.     }
  231.  
  232.     icon->image = wIconValidateIconSize(scr, icon->image);
  233.     
  234.     icon->file = wstrdup(iconfile);
  235.     }
  236.     
  237.     icon->tile_type = tile;
  238.     
  239.     wIconUpdate(icon);
  240.  
  241.     WMAddNotificationObserver(appearanceObserver, icon, 
  242.                   WNIconAppearanceSettingsChanged, icon);
  243.     WMAddNotificationObserver(tileObserver, icon, 
  244.                   WNIconTileSettingsChanged, icon);
  245.  
  246.     return icon;
  247. }
  248.  
  249.  
  250.  
  251. void
  252. wIconDestroy(WIcon *icon)
  253. {
  254.     WCoreWindow *core = icon->core;
  255.     WScreen *scr = core->screen_ptr;
  256.  
  257.     WMRemoveNotificationObserver(icon);
  258.  
  259.     if (icon->handlerID)
  260.     WMDeleteTimerHandler(icon->handlerID);
  261.  
  262.     if (icon->icon_win) {
  263.     int x=0, y=0;
  264.  
  265.     if (icon->owner) {
  266.         x = icon->owner->icon_x;
  267.         y = icon->owner->icon_y;
  268.     }
  269.     XUnmapWindow(dpy, icon->icon_win);
  270.     XReparentWindow(dpy, icon->icon_win, scr->root_win, x, y);
  271.     }
  272.     if (icon->icon_name)
  273.       XFree(icon->icon_name);
  274.  
  275.     if (icon->pixmap)
  276.       XFreePixmap(dpy, icon->pixmap);
  277.  
  278.     if (icon->file)
  279.         free(icon->file);
  280.  
  281.     if (icon->image!=NULL)
  282.     RDestroyImage(icon->image);
  283.  
  284.     wCoreDestroy(icon->core);
  285.     free(icon);
  286. }
  287.  
  288.  
  289.  
  290. static void
  291. drawIconTitle(WScreen *scr, Pixmap pixmap, int height)
  292. {
  293.     XFillRectangle(dpy, pixmap, scr->icon_title_texture->normal_gc,
  294.            0, 0, wPreferences.icon_size, height+1);
  295.     XDrawLine(dpy, pixmap, scr->icon_title_texture->light_gc, 0, 0,
  296.           wPreferences.icon_size, 0);
  297.     XDrawLine(dpy, pixmap, scr->icon_title_texture->light_gc, 0, 0,
  298.           0, height+1);
  299.     XDrawLine(dpy, pixmap, scr->icon_title_texture->dim_gc, 
  300.           wPreferences.icon_size-1, 0, wPreferences.icon_size-1, height+1);
  301. }
  302.  
  303.  
  304. static Pixmap
  305. makeIcon(WScreen *scr, RImage *icon, int titled, int shadowed, int tileType)
  306. {
  307.     RImage *tile;
  308.     Pixmap pixmap;
  309.     int x, y, sx, sy;
  310.     unsigned w, h;
  311.     int theight = WMFontHeight(scr->icon_title_font);
  312.     
  313.     if (tileType == TILE_NORMAL)
  314.     tile = RCloneImage(scr->icon_tile);
  315.     else {
  316.     assert(scr->clip_tile);
  317.     tile = RCloneImage(scr->clip_tile);
  318.     }
  319.     if (icon) {
  320.     w = (icon->width > wPreferences.icon_size) 
  321.         ? wPreferences.icon_size : icon->width;
  322.     x = (wPreferences.icon_size - w) / 2;
  323.     sx = (icon->width - w)/2;
  324.     
  325.     if (!titled) {
  326.         h = (icon->height > wPreferences.icon_size) 
  327.         ? wPreferences.icon_size : icon->height;
  328.         y = (wPreferences.icon_size - h) / 2;
  329.         sy = (icon->height - h)/2;
  330.     } else {
  331.         h = (icon->height+theight > wPreferences.icon_size
  332.          ? wPreferences.icon_size-theight : icon->height);
  333.         y = theight+((int)wPreferences.icon_size-theight-h)/2;
  334.         sy = (icon->height - h)/2;
  335.     }
  336.     RCombineArea(tile, icon, sx, sy, w, h, x, y);
  337.     }
  338.  
  339.     if (shadowed) {
  340.         RColor color;
  341.  
  342.         color.red   = scr->icon_back_texture->light.red   >> 8;
  343.         color.green = scr->icon_back_texture->light.green >> 8;
  344.         color.blue  = scr->icon_back_texture->light.blue  >> 8;
  345.         color.alpha = 150; /* about 60% */
  346.         RClearImage(tile, &color);
  347.     }
  348.  
  349.     if (!RConvertImage(scr->rcontext, tile, &pixmap)) {
  350.     wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
  351.     }
  352.     RDestroyImage(tile);
  353.  
  354.     if (titled)
  355.       drawIconTitle(scr, pixmap, theight);
  356.  
  357.     return pixmap;
  358. }
  359.  
  360.  
  361. void
  362. wIconChangeTitle(WIcon *icon, char *new_title)
  363. {
  364.     int changed;
  365.  
  366.     changed = (new_title==NULL && icon->icon_name!=NULL)
  367.     || (new_title!=NULL && icon->icon_name==NULL);
  368.  
  369.     if (icon->icon_name!=NULL)
  370.     XFree(icon->icon_name);
  371.  
  372.     icon->icon_name = new_title;
  373.  
  374.     if (changed)
  375.         icon->force_paint = 1;
  376.     wIconPaint(icon);
  377. }
  378.  
  379.  
  380. void
  381. wIconChangeImage(WIcon *icon, RImage *new_image)
  382. {
  383.     assert(icon != NULL);
  384.     
  385.     if (icon->image)
  386.         RDestroyImage(icon->image);
  387.  
  388.     icon->image = wIconValidateIconSize(icon->core->screen_ptr, new_image);
  389.  
  390.     wIconUpdate(icon);
  391. }
  392.  
  393.  
  394. RImage*
  395. wIconValidateIconSize(WScreen *scr, RImage *icon)
  396. {
  397.     RImage *tmp;
  398.     int w, h;
  399.     
  400.     if (!icon)
  401.     return NULL;
  402. #ifndef DONT_SCALE_ICONS
  403.     if (wPreferences.icon_size != 64) {
  404.     w = wPreferences.icon_size * icon->width / 64;
  405.     h = wPreferences.icon_size * icon->height / 64;
  406.  
  407.     tmp = RScaleImage(icon, w, h);
  408.     RDestroyImage(icon);
  409.     icon = tmp;
  410.     }
  411. #endif
  412. #if 0
  413.     if (icon->width > wPreferences.icon_size
  414.         || icon->height > wPreferences.icon_size) {
  415.     if (icon->width > icon->height) {
  416.         w = wPreferences.icon_size - 4;
  417.         h = w*icon->height/icon->width;
  418.     } else {
  419.         h = wPreferences.icon_size - 4;
  420.         w = h*icon->width/icon->height;
  421.     }
  422.     tmp = RScaleImage(icon, w, h);
  423.     RDestroyImage(icon);
  424.     icon = tmp;
  425.     }
  426. #endif
  427.  
  428.     return icon;
  429. }
  430.  
  431.  
  432. Bool
  433. wIconChangeImageFile(WIcon *icon, char *file)
  434. {
  435.     WScreen *scr = icon->core->screen_ptr;
  436.     RImage *image;
  437.     char *path;
  438.     int error = 0;
  439.  
  440.     if (!file) {
  441.     wIconChangeImage(icon, NULL);
  442.     return True;
  443.     }
  444.  
  445.     path = FindImage(wPreferences.icon_path, file);
  446.  
  447.     if (path && (image = RLoadImage(scr->rcontext, path, 0))) {
  448.     wIconChangeImage(icon, image);
  449.     } else {
  450.     error = 1;
  451.     }
  452.  
  453.     if (path)
  454.     free(path);
  455.  
  456.     return !error;
  457. }
  458.  
  459.  
  460.  
  461. static char*
  462. getnameforicon(WWindow *wwin)
  463. {
  464.     char *prefix, *suffix;
  465.     char *path;
  466.     int len;
  467.     
  468.     if (wwin->wm_class && wwin->wm_instance) {
  469.     suffix = wmalloc(strlen(wwin->wm_class)+strlen(wwin->wm_instance)+2);
  470.     sprintf(suffix, "%s.%s", wwin->wm_instance, wwin->wm_class);
  471.     } else if (wwin->wm_class) {
  472.     suffix = wmalloc(strlen(wwin->wm_class)+1);
  473.     strcpy(suffix, wwin->wm_class);
  474.     } else if (wwin->wm_instance) {
  475.     suffix = wmalloc(strlen(wwin->wm_instance)+1);
  476.     strcpy(suffix, wwin->wm_instance);
  477.     } else {
  478.     return NULL;
  479.     }
  480.  
  481.     prefix = wusergnusteppath();
  482.     len = strlen(prefix)+64+strlen(suffix);
  483.     path = wmalloc(len+1);
  484.     sprintf(path, "%s/.AppInfo", prefix);
  485.  
  486.     if (access(path, F_OK)!=0) {
  487.     if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR)) {
  488.         wsyserror(_("could not create directory %s"), path);
  489.         free(path);
  490.         free(suffix);
  491.         return NULL;
  492.     }
  493.     }
  494.     strcat(path, "/WindowMaker");
  495.     if (access(path, F_OK)!=0) {
  496.     if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR)!=0) {
  497.         wsyserror(_("could not create directory %s"), path);
  498.         free(path);
  499.         free(suffix);
  500.         return NULL;
  501.     }
  502.     }
  503.  
  504.     strcat(path, "/");
  505.     strcat(path, suffix);
  506.     strcat(path, ".xpm");
  507.     free(suffix);
  508.  
  509.     return path;
  510. }
  511.  
  512.  
  513. /*
  514.  * wIconStore--
  515.  *     Stores the client supplied icon at ~/GNUstep/.AppInfo/WindowMaker
  516.  * and returns the path for that icon. Returns NULL if there is no
  517.  * client supplied icon or on failure.
  518.  * 
  519.  * Side effects:
  520.  *     New directories might be created.
  521.  */
  522. char*
  523. wIconStore(WIcon *icon)
  524. {
  525.     char *path;
  526.     RImage *image;
  527.     WWindow *wwin = icon->owner;
  528.  
  529.     if (!wwin || !wwin->wm_hints || !(wwin->wm_hints->flags & IconPixmapHint)
  530.     || wwin->wm_hints->icon_pixmap == None)
  531.     return NULL;
  532.  
  533.     path = getnameforicon(wwin);
  534.     if (!path)
  535.     return NULL;
  536.  
  537.     image = RCreateImageFromDrawable(icon->core->screen_ptr->rcontext,
  538.                      wwin->wm_hints->icon_pixmap,
  539.                      (wwin->wm_hints->flags & IconMaskHint)
  540.                      ? wwin->wm_hints->icon_mask : None);
  541.     if (!image) {
  542.     free(path);
  543.     return NULL;
  544.     }
  545.  
  546.     if (!RSaveImage(image, path, "XPM")) {
  547.     free(path);
  548.     path = NULL;
  549.     }
  550.     RDestroyImage(image);
  551.  
  552.     return path;
  553. }
  554.  
  555.  
  556. /*
  557. void
  558. wIconChangeIconWindow(WIcon *icon, Window new_window);
  559. */
  560.  
  561. static void 
  562. cycleColor(void *data)
  563. {
  564.     WIcon *icon = (WIcon*)data;
  565.     WScreen *scr = icon->core->screen_ptr;
  566.     XGCValues gcv;
  567.  
  568.     icon->step--;
  569.     gcv.dash_offset = icon->step;
  570.     XChangeGC(dpy, scr->icon_select_gc, GCDashOffset, &gcv);
  571.  
  572.     XDrawRectangle(dpy, icon->core->window, scr->icon_select_gc, 0, 0,
  573.            icon->core->width-1, icon->core->height-1);
  574.     icon->handlerID = WMAddTimerHandler(COLOR_CYCLE_DELAY, cycleColor, icon);
  575. }
  576.  
  577.  
  578. void
  579. wIconSetHighlited(WIcon *icon, Bool flag)
  580. {
  581.     if (icon->highlighted == flag) {
  582.     return;
  583.     }
  584.     
  585.     icon->highlighted = flag;
  586.     wIconPaint(icon);
  587. }
  588.  
  589.  
  590.  
  591. void
  592. wIconSelect(WIcon *icon)
  593. {
  594.     WScreen *scr = icon->core->screen_ptr;
  595.     icon->selected = !icon->selected;
  596.  
  597.     if (icon->selected) {
  598.         icon->step = 0;
  599.     if (!wPreferences.dont_blink)
  600.             icon->handlerID = WMAddTimerHandler(10, cycleColor, icon);
  601.         else
  602.             XDrawRectangle(dpy, icon->core->window, scr->icon_select_gc, 0, 0,
  603.                            icon->core->width-1, icon->core->height-1);
  604.     } else {
  605.         if (icon->handlerID) {
  606.             WMDeleteTimerHandler(icon->handlerID);
  607.             icon->handlerID = NULL;
  608.         }
  609.     XClearArea(dpy, icon->core->window, 0, 0, icon->core->width,
  610.            icon->core->height, True);
  611.     }
  612. }
  613.  
  614.  
  615. void
  616. wIconUpdate(WIcon *icon)
  617. {
  618.     WScreen *scr = icon->core->screen_ptr;
  619.     int title_height = WMFontHeight(scr->icon_title_font);
  620.     WWindow *wwin = icon->owner;
  621.  
  622.     assert(scr->icon_tile!=NULL);
  623.  
  624.     if (icon->pixmap!=None)
  625.     XFreePixmap(dpy, icon->pixmap);
  626.     icon->pixmap = None;
  627.     
  628.     
  629.     if (wwin && WFLAGP(wwin, always_user_icon))
  630.     goto user_icon;
  631.     
  632.     /* use client specified icon window */
  633.     if (icon->icon_win!=None) {
  634.     XWindowAttributes attr;
  635.     int resize=0;
  636.     int width, height, depth;
  637.     int theight;
  638.     Pixmap pixmap;
  639.  
  640.     getSize(icon->icon_win, &width, &height, &depth);
  641.  
  642.     if (width > wPreferences.icon_size) {
  643.         resize = 1;
  644.         width = wPreferences.icon_size;
  645.     }
  646.     if (height > wPreferences.icon_size) {
  647.         resize = 1;
  648.         height = wPreferences.icon_size;
  649.     }
  650.     if (icon->show_title 
  651.         && (height+title_height < wPreferences.icon_size)) {
  652.         pixmap = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size,
  653.                    wPreferences.icon_size, scr->w_depth);
  654.         XSetClipMask(dpy, scr->copy_gc, None);
  655.         XCopyArea(dpy, scr->icon_tile_pixmap, pixmap, scr->copy_gc, 0, 0,
  656.               wPreferences.icon_size, wPreferences.icon_size, 0, 0);
  657.         drawIconTitle(scr, pixmap, title_height);
  658.         theight = title_height;
  659.     } else {
  660.         pixmap = None;
  661.         theight = 0;
  662.         XSetWindowBackgroundPixmap(dpy, icon->core->window,
  663.                        scr->icon_tile_pixmap);
  664.     }
  665.     
  666.     XSetWindowBorderWidth(dpy, icon->icon_win, 0);
  667.     XReparentWindow(dpy, icon->icon_win, icon->core->window,
  668.             (wPreferences.icon_size-width)/2,
  669.             theight+(wPreferences.icon_size-height-theight)/2);
  670.     if (resize)
  671.       XResizeWindow(dpy, icon->icon_win, width, height);
  672.  
  673.     XMapWindow(dpy, icon->icon_win);
  674.     
  675.     XAddToSaveSet(dpy, icon->icon_win);
  676.     
  677.     icon->pixmap = pixmap;
  678.  
  679.     if (XGetWindowAttributes(dpy, icon->icon_win, &attr)) {
  680.         if (attr.all_event_masks & ButtonPressMask) {
  681.         wHackedGrabButton(Button1, MOD_MASK, icon->core->window, True, 
  682.                   ButtonPressMask, GrabModeSync, GrabModeAsync,
  683.                   None, wCursor[WCUR_ARROW]);
  684.         }
  685.     }
  686.     } else if (wwin && wwin->wm_hints
  687.            && (wwin->wm_hints->flags & IconPixmapHint)) {
  688.     int x, y;
  689.     unsigned int w, h;
  690.     Window jw;
  691.     int ji, dotitle;
  692.     unsigned int ju, d;
  693.     Pixmap pixmap;
  694.     
  695.     if (!XGetGeometry(dpy, wwin->wm_hints->icon_pixmap, &jw, 
  696.               &ji, &ji, &w, &h, &ju, &d)) {
  697.         icon->owner->wm_hints->flags &= ~IconPixmapHint;
  698.         goto user_icon;
  699.     }
  700.             
  701.     pixmap = XCreatePixmap(dpy, icon->core->window, wPreferences.icon_size,
  702.                    wPreferences.icon_size, scr->w_depth);
  703.     XSetClipMask(dpy, scr->copy_gc, None);
  704.     XCopyArea(dpy, scr->icon_tile_pixmap, pixmap, scr->copy_gc, 0, 0,
  705.           wPreferences.icon_size, wPreferences.icon_size, 0, 0);
  706.  
  707.     if (w > wPreferences.icon_size)
  708.         w = wPreferences.icon_size;
  709.     x = (wPreferences.icon_size-w)/2;
  710.  
  711.     if (icon->show_title && (title_height < wPreferences.icon_size)) {
  712.         drawIconTitle(scr, pixmap, title_height);
  713.         dotitle = 1;
  714.         
  715.         if (h > wPreferences.icon_size - title_height - 2) {
  716.         h = wPreferences.icon_size - title_height - 2;
  717.         y = title_height + 1;
  718.         } else {
  719.         y = (wPreferences.icon_size-h-title_height)/2+title_height + 1;
  720.         }
  721.     } else {
  722.         dotitle = 0;
  723.         if (w > wPreferences.icon_size)
  724.         w = wPreferences.icon_size;
  725.         y = (wPreferences.icon_size-h)/2;
  726.     }
  727.  
  728.     if (wwin->wm_hints->flags & IconMaskHint)
  729.         XSetClipMask(dpy, scr->copy_gc, wwin->wm_hints->icon_mask);
  730.     
  731.     XSetClipOrigin(dpy, scr->copy_gc, x, y);
  732.     
  733.     if (d != scr->w_depth) {
  734.         XSetForeground(dpy, scr->copy_gc, scr->black_pixel);
  735.         XSetBackground(dpy, scr->copy_gc, scr->white_pixel);
  736.         XCopyPlane(dpy, wwin->wm_hints->icon_pixmap, pixmap, scr->copy_gc,
  737.               0, 0, w, h, x, y, 1);
  738.     } else {
  739.         XCopyArea(dpy, wwin->wm_hints->icon_pixmap, pixmap, scr->copy_gc,
  740.               0, 0, w, h, x, y);
  741.     }
  742.     
  743.     XSetClipOrigin(dpy, scr->copy_gc, 0, 0);
  744.     
  745.     icon->pixmap = pixmap;
  746.     } else {
  747.       user_icon:
  748.  
  749.           if (icon->image) {
  750.               icon->pixmap = makeIcon(scr, icon->image, icon->show_title,
  751.                       icon->shadowed, icon->tile_type);
  752.           } else {
  753.               /* make default icons */
  754.  
  755.               if (!scr->def_icon_pixmap) {
  756.                   RImage *image = NULL;
  757.                   char *path;
  758.                   char *file;
  759.  
  760.                   file = wDefaultGetIconFile(scr, NULL, NULL, False);
  761.                   if (file) {
  762.                       path = FindImage(wPreferences.icon_path, file);
  763.                       if (!path) {
  764.                           wwarning(_("could not find default icon \"%s\""),file);
  765.                           goto make_icons;
  766.                       }
  767.  
  768.                       image = RLoadImage(scr->rcontext, path, 0);
  769.                       if (!image) {
  770.                           wwarning(_("could not load default icon \"%s\":%s"),
  771.                    file, RMessageForError(RErrorCode));
  772.                       }
  773.                       free(path);
  774.                   }
  775.     make_icons:
  776.           
  777.           image = wIconValidateIconSize(scr, image);
  778.                   scr->def_icon_pixmap = makeIcon(scr, image, False, False,
  779.                           icon->tile_type);
  780.                   scr->def_ticon_pixmap = makeIcon(scr, image, True, False,
  781.                            icon->tile_type);
  782.           if (image)
  783.               RDestroyImage(image);
  784.               }
  785.  
  786.               if (icon->show_title) {
  787.                   XSetWindowBackgroundPixmap(dpy, icon->core->window,
  788.                                              scr->def_ticon_pixmap);
  789.               } else {
  790.                   XSetWindowBackgroundPixmap(dpy, icon->core->window,
  791.                                              scr->def_icon_pixmap);
  792.               }
  793.               icon->pixmap = None;
  794.           }
  795.     }
  796.     if (icon->pixmap != None) {
  797.         XSetWindowBackgroundPixmap(dpy, icon->core->window, icon->pixmap);
  798.     }
  799.     XClearWindow(dpy, icon->core->window);
  800.  
  801.     wIconPaint(icon);
  802. }
  803.  
  804.  
  805.  
  806. void
  807. wIconPaint(WIcon *icon)
  808. {
  809.     WScreen *scr=icon->core->screen_ptr;
  810.     GC gc = scr->icon_title_gc;
  811.     int x;
  812.     char *tmp;
  813.  
  814.     if (icon->force_paint) {
  815.         icon->force_paint = 0;
  816.         wIconUpdate(icon);
  817.         return;
  818.     }
  819.  
  820.     XClearWindow(dpy, icon->core->window);
  821.  
  822.     /* draw the icon title */
  823.     if (icon->show_title && icon->icon_name!=NULL) {
  824.     int l;
  825.     int w;
  826.  
  827.     tmp = ShrinkString(scr->icon_title_font, icon->icon_name,
  828.                wPreferences.icon_size-4);
  829.     w = WMWidthOfString(scr->icon_title_font, tmp, l=strlen(tmp));
  830.  
  831.     if (w > icon->core->width - 4)
  832.       x = (icon->core->width - 4) - w;
  833.     else
  834.       x = (icon->core->width - w)/2;
  835.  
  836.     WMDrawString(scr->wmscreen, icon->core->window, gc,
  837.              scr->icon_title_font, x, 1, tmp, l);
  838.     free(tmp);
  839.     }
  840.  
  841.     if (icon->selected)
  842.     XDrawRectangle(dpy, icon->core->window, scr->icon_select_gc, 0, 0,
  843.                icon->core->width-1, icon->core->height-1);
  844. }
  845.  
  846.  
  847. /******************************************************************/
  848.  
  849. static void
  850. miniwindowExpose(WObjDescriptor *desc, XEvent *event)
  851. {
  852.     wIconPaint(desc->parent);
  853. }
  854.  
  855.  
  856. static void
  857. miniwindowDblClick(WObjDescriptor *desc, XEvent *event)
  858. {
  859.     WIcon *icon = desc->parent;
  860.  
  861.     assert(icon->owner!=NULL);
  862.  
  863.     wDeiconifyWindow(icon->owner);
  864. }
  865.  
  866.  
  867. static void 
  868. miniwindowMouseDown(WObjDescriptor *desc, XEvent *event)
  869. {
  870.     WIcon *icon = desc->parent;
  871.     WWindow *wwin = icon->owner;
  872.     XEvent ev;
  873.     int x=wwin->icon_x, y=wwin->icon_y;
  874.     int dx=event->xbutton.x, dy=event->xbutton.y;
  875.     int grabbed=0;
  876.     int clickButton=event->xbutton.button;
  877.  
  878.     if (WCHECK_STATE(WSTATE_MODAL))
  879.     return;
  880.  
  881.     if (IsDoubleClick(icon->core->screen_ptr, event)) {
  882.     miniwindowDblClick(desc, event);
  883.     return;
  884.     }
  885.     
  886. #ifdef DEBUG
  887.     puts("Moving miniwindow");
  888. #endif
  889.     if (event->xbutton.button == Button1) {    
  890.     if (event->xbutton.state & MOD_MASK)
  891.         wLowerFrame(icon->core);
  892.     else
  893.         wRaiseFrame(icon->core);
  894.         if (event->xbutton.state & ShiftMask) {
  895.             wIconSelect(icon);
  896.             wSelectWindow(icon->owner, !wwin->flags.selected);
  897.         }
  898.     } else if (event->xbutton.button == Button3) {
  899.     WObjDescriptor *desc;
  900.  
  901.     OpenMiniwindowMenu(wwin, event->xbutton.x_root, 
  902.                event->xbutton.y_root);
  903.  
  904.     /* allow drag select of menu */
  905.     desc = &wwin->screen_ptr->window_menu->menu->descriptor;
  906.     event->xbutton.send_event = True;
  907.     (*desc->handle_mousedown)(desc, event);
  908.  
  909.     return;
  910.     }
  911.  
  912.     if (XGrabPointer(dpy, icon->core->window, False, ButtonMotionMask
  913.              |ButtonReleaseMask|ButtonPressMask, GrabModeAsync,
  914.              GrabModeAsync, None, None, CurrentTime) !=GrabSuccess) {
  915. #ifdef DEBUG0
  916.     wwarning("pointer grab failed for icon move");
  917. #endif
  918.     }
  919.     while(1) {
  920.     WMMaskEvent(dpy, PointerMotionMask|ButtonReleaseMask|ButtonPressMask
  921.            |ButtonMotionMask|ExposureMask, &ev);
  922.     switch (ev.type) {
  923.      case Expose:
  924.         WMHandleEvent(&ev);
  925.         break;
  926.  
  927.      case MotionNotify:
  928.         if (!grabbed) {
  929.         if (abs(dx-ev.xmotion.x)>=MOVE_THRESHOLD
  930.             || abs(dy-ev.xmotion.y)>=MOVE_THRESHOLD) {
  931.             XChangeActivePointerGrab(dpy, ButtonMotionMask
  932.                         |ButtonReleaseMask|ButtonPressMask, 
  933.                          wCursor[WCUR_MOVE], CurrentTime);
  934.             grabbed=1;
  935.         } else {
  936.             break;
  937.         }
  938.         }
  939.         x = ev.xmotion.x_root - dx;
  940.         y = ev.xmotion.y_root - dy;
  941.         XMoveWindow(dpy, icon->core->window, x, y);
  942.         break;
  943.  
  944.      case ButtonPress:
  945.         break;
  946.  
  947.      case ButtonRelease:
  948.         if (ev.xbutton.button != clickButton)
  949.         break;
  950.  
  951.         if (wwin->icon_x!=x || wwin->icon_y!=y)
  952.           wwin->flags.icon_moved = 1;
  953.  
  954.         XMoveWindow(dpy, icon->core->window, x, y);
  955.  
  956.         wwin->icon_x = x;
  957.         wwin->icon_y = y;
  958. #ifdef DEBUG
  959.         puts("End miniwindow move");
  960. #endif
  961.         XUngrabPointer(dpy, CurrentTime);
  962.  
  963.         if (wPreferences.auto_arrange_icons)
  964.         wArrangeIcons(wwin->screen_ptr, True);
  965.         return;
  966.         
  967.     }
  968.     }
  969. }
  970.  
  971.  
  972.